/**
 *    Copyright (C) 2007-2009 DIVIS GmbH (http://www.divis-hagen.de/)
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License as published by the Free Software Foundation; either
 *    version 3 of the License, or (at your option) any later version.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General
 *    Public License along with this library; if not, write to the
 *    Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 *    Boston, MA 02110-1301 USA
 */

package de.divis_hagen.json.rs.client;

import de.divis_hagen.json.Helpers;
import de.divis_hagen.json.JSONContextImpl;
import de.divis_hagen.json.TypeMeta;
import de.divis_hagen.json.annotation.JSONCollectionResource;
import java.lang.reflect.Type;
import java.util.Collection;


/**
 *
 * @author Aike J Sommer
 */
public class ResourceInfo {

//    private static final Pattern segmentPattern = Pattern.compile("\\{[a-zA-Z0-9]*: ([a-zA-Z0-9]*)\\}");

    private final Class elementType;
//    private final Class collectionType;
//    private final Class handler;
//    private final String simpleName;
//    private final String entityTypeName;
    private final String handlerTypeName;
    private final String handlerInstanceName;
//    private final String rootPath;
//    private final RequestInfo loadRequest;
//    private final RequestInfo listRequest;
//    private final TreeBuilder builder;
    private final String collectionPath;
    private final String collectionElements;
    private final JSONContextImpl context;

//    private JSONObject jsonObject;

    public ResourceInfo(JSONContextImpl context, Class collectionType, String basePackage) {
        this.context = context;
//        this.collectionType = collectionType;
        JSONCollectionResource collection = (JSONCollectionResource) collectionType.getAnnotation(JSONCollectionResource.class);
        elementType = findElementType(collectionType, collection.elements());

//        this.handler = handler;
//        simpleName = (elementType.isAnnotationPresent(JSONElementName.class) ? ((JSONElementName) elementType.getAnnotation(JSONElementName.class)).value()
//                : elementType.getSimpleName());
//        entityTypeName = simpleName;
        handlerTypeName = context.meta(elementType).getName() + "Handler";

//        if (handler.isAnnotationPresent(Path.class)) {
//            String path = ((Path) handler.getAnnotation(Path.class)).value();
//            if (path.endsWith("/")) {
//                path = path.substring(0, path.length() - 1);
//            }
//            rootPath = path.startsWith("/") || path.isEmpty() ? path : ("/" + path);
//            if (path.startsWith("/")) {
//                path = path.substring(1);
//            }
//            handlerInstanceName = cleanPath(path);
//        } else {
//            throw new IllegalArgumentException(handler.getName());
//        }
//        if (collection.path().equals(ElementResource.DEFAULT_STRING)
//                || collection.handler().equals(ElementResource.DEFAULT_STRING)) {
//            rootPath = null;
//            handlerInstanceName = null;
//        } else {
        collectionPath = collection.path();
        handlerInstanceName = collection.handler();
        collectionElements = collection.elements();
//        }

//        final EntityInfo self = this;
//        loadRequest = RequestInfo.find(EntityRequest.Type.Load, self);
//        listRequest = RequestInfo.find(EntityRequest.Type.List, self);
    }

//    public Class getElementType() {
//        return elementType;
//    }

    public String getCollectionPath() {
        return collectionPath;
    }

    public String getCollectionElements() {
        return collectionElements;
    }

    private Class findElementType(Class in, String name) {
        Type type = getType(in, name);
        return (Class) Helpers.getTypes(type, Collection.class)[0];
    }

//    public JSONObject getJSONObject() throws JSONException {
//        if (jsonObject != null) {
//            return jsonObject;
//        }
//
//        JSONTree tree = builder.build(elementType);
//        jsonObject = (JSONObject) tree.getRoot();
//        jsonObject = (JSONObject) jsonObject.get(jsonObject.getNames().iterator().next());
//        return jsonObject;
//    }

    private String upperFirst(String value) {
        return value.substring(0, 1).toUpperCase() + value.substring(1);
    }

    public Type getType(String name) {
        return getType(elementType, name);
    }

    private Type getType(Class in, String name) {
        Type type;
        try {
            type = in.getDeclaredField(name).getGenericType();
        } catch (NoSuchFieldException ex) {
            try {
                type = in.getMethod("get" + upperFirst(name)).getGenericReturnType();
            } catch (NoSuchMethodException ex2) {
                throw new IllegalArgumentException(name);
            }
        }
        return type;
    }

//    private String cleanPath(String path) {
//        path = path.replace("/", "_");
//
//        Matcher m = segmentPattern.matcher(path);
//        if (m.matches()) {
//            path = m.group(1);
//        }
//
//        return path;
//    }

//    public Class getEntity() {
//        return elementType;
//    }

//    public String getSimpleName() {
//        return simpleName;
//    }
//
//    public String getElementTypeName() {
//        return entityTypeName;
//    }

    public String getHandlerTypeName() {
        return handlerTypeName;
    }

    public String getHandlerInstanceName() {
        return handlerInstanceName;
    }

//    public String getRootPath() {
//        return rootPath;
//    }

//    protected Class getHandler() {
//        return handler;
//    }

//    public RequestInfo getLoadRequest() {
//        return loadRequest;
//    }
//
//    public RequestInfo getListRequest() {
//        return listRequest;
//    }

    public TypeMeta.Complex<Object> getElement() {
        return (TypeMeta.Complex) context.meta(elementType);
    }

}
